package ssq.gamest.webserver;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

import org.apache.http.HttpException;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.DefaultHttpResponseFactory;
import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.HttpRequestHandler;
import org.apache.http.protocol.HttpRequestHandlerRegistry;
import org.apache.http.protocol.HttpService;
import org.apache.http.protocol.ResponseConnControl;
import org.apache.http.protocol.ResponseContent;
import org.apache.http.protocol.ResponseDate;
import org.apache.http.protocol.ResponseServer;

import ssq.gamest.websocketserver.GameCommunicationServer;

public class WebServer extends Thread
{
    private boolean                    isRunning   = false;
    private int                        port        = 0;
    private int                        wsport      = 0;
    
    private BasicHttpProcessor         httpproc    = null;
    private BasicHttpContext           httpContext = null;
    private HttpService                httpService = null;
    private HttpRequestHandlerRegistry registry    = null;
    
    private ServerSocket               serverSocket;
    private GameCommunicationServer    wsServer;
    
    public WebServer(String name, int port, int wsport)
    {
        super(name);
        
        this.port = port;
        this.wsport = wsport;
        httpproc = new BasicHttpProcessor();
        httpContext = new BasicHttpContext();
        
        httpproc.addInterceptor(new ResponseDate());
        httpproc.addInterceptor(new ResponseServer());
        httpproc.addInterceptor(new ResponseContent());
        httpproc.addInterceptor(new ResponseConnControl());
        
        httpService = new HttpService(httpproc, new DefaultConnectionReuseStrategy(), new DefaultHttpResponseFactory());
        
        registry = new HttpRequestHandlerRegistry();
    }
    
    public WebServer registerHandler(String pattern, HttpRequestHandler handler)
    {
        registry.register(pattern, handler);
        return this;
    }
    
    public WebServer create()
    {
        httpService.setHandlerResolver(registry);
        return this;
    }
    
    @Override
    public void run()
    {
        super.run();
        
        try
        {
            serverSocket = new ServerSocket(port);
            serverSocket.setReuseAddress(true);
            
            while (isRunning)
            {
                try
                {
                    final Socket socket = serverSocket.accept();
                    Thread proceedRequest = new Thread()
                    {
                        @Override
                        public void run()
                        {
                            DefaultHttpServerConnection serverConnection = new DefaultHttpServerConnection();
                            try
                            {
                                serverConnection.bind(socket, new BasicHttpParams());
                                httpService.handleRequest(serverConnection, httpContext);
                                serverConnection.shutdown();
                            }
                            catch (IOException e)
                            {
                                e.printStackTrace();
                            }
                            catch (HttpException e)
                            {
                                e.printStackTrace();
                            }
                        }
                    };
                    proceedRequest.start();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
            serverSocket.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
    
    @Override
    public synchronized void start()
    {
        isRunning = true;
        super.start();
        try
        {
            wsServer = GameCommunicationServer.runAndGetServer(new String[] { "-p", String.valueOf(wsport) });
        }
        catch (UnknownHostException e)
        {
            e.printStackTrace();
        }
    }
    
    public synchronized void stopThread()
    {
        isRunning = false;
        try
        {
            serverSocket.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        
        try
        {
            wsServer.stop();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}
